<template>
	<view class="uni-table-scroll" :class="{ 'table--border': border, 'border-none': !noData }">
		<!-- #ifdef H5 -->
		<table class="uni-table" border="0" cellpadding="0" cellspacing="0" :class="{ 'table--stripe': stripe }" :style="{ 'min-width': minWidth + 'px' }">
			<slot></slot>
			<view v-if="noData" class="uni-table-loading">
				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
			</view>
			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
		</table>
		<!-- #endif -->
		<!-- #ifndef H5 -->
		<view class="uni-table" :style="{ 'min-width': minWidth + 'px' }" :class="{ 'table--stripe': stripe }">
			<slot></slot>
			<view v-if="noData" class="uni-table-loading">
				<view class="uni-table-text" :class="{ 'empty-border': border }">{{ emptyText }}</view>
			</view>
			<view v-if="loading" class="uni-table-mask" :class="{ 'empty-border': border }"><div class="uni-table--loader"></div></view>
		</view>
		<!-- #endif -->
	</view>
</template>

<script>
/**
 * Table 表格
 * @description 用于展示多条结构类似的数据
 * @tutorial https://ext.dcloud.net.cn/plugin?id=3270
 * @property {Boolean} 	border 				是否带有纵向边框
 * @property {Boolean} 	stripe 				是否显示斑马线
 * @property {Boolean} 	type 					是否开启多选
 * @property {String} 	emptyText 			空数据时显示的文本内容
 * @property {Boolean} 	loading 			显示加载中
 * @event {Function} 	selection-change 	开启多选时，当选择项发生变化时会触发该事件
 */
export default {
  name: 'uniTable',
  options: {
    virtualHost: true
  },
  emits: ['selection-change'],
  props: {
    data: {
      type: Array,
      default () {
        return []
      }
    },
    // 是否有竖线
    border: {
      type: Boolean,
      default: false
    },
    // 是否显示斑马线
    stripe: {
      type: Boolean,
      default: false
    },
    // 多选
    type: {
      type: String,
      default: ''
    },
    // 没有更多数据
    emptyText: {
      type: String,
      default: '没有更多数据'
    },
    loading: {
      type: Boolean,
      default: false
    },
    rowKey: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      noData: true,
      minWidth: 0,
      multiTableHeads: []
    }
  },
  watch: {
    loading (val) {},
    data (newVal) {
      const theadChildren = this.theadChildren
      let rowspan = 1
      if (this.theadChildren) {
        rowspan = this.theadChildren.rowspan
      }

      // this.trChildren.length - rowspan
      this.noData = false
      // this.noData = newVal.length === 0
    }
  },
  created () {
    // 定义tr的实例数组
    this.trChildren = []
    this.thChildren = []
    this.theadChildren = null
    this.backData = []
    this.backIndexData = []
  },

  methods: {
    isNodata () {
      const theadChildren = this.theadChildren
      let rowspan = 1
      if (this.theadChildren) {
        rowspan = this.theadChildren.rowspan
      }
      this.noData = this.trChildren.length - rowspan <= 0
    },
    /**
		 * 选中所有
		 */
    selectionAll () {
      let startIndex = 1
      let theadChildren = this.theadChildren
      if (!this.theadChildren) {
        theadChildren = this.trChildren[0]
      } else {
        startIndex = theadChildren.rowspan - 1
      }
      const isHaveData = this.data && this.data.length.length > 0
      theadChildren.checked = true
      theadChildren.indeterminate = false
      this.trChildren.forEach((item, index) => {
        if (!item.disabled) {
          item.checked = true
          if (isHaveData && item.keyValue) {
            const row = this.data.find(v => v[this.rowKey] === item.keyValue)
            if (!this.backData.find(v => v[this.rowKey] === row[this.rowKey])) {
              this.backData.push(row)
            }
          }
          if (index > (startIndex - 1) && this.backIndexData.indexOf(index - startIndex) === -1) {
            this.backIndexData.push(index - startIndex)
          }
        }
      })
      // this.backData = JSON.parse(JSON.stringify(this.data))
      this.$emit('selection-change', {
        detail: {
          value: this.backData,
          index: this.backIndexData
        }
      })
    },
    /**
		 * 用于多选表格，切换某一行的选中状态，如果使用了第二个参数，则是设置这一行选中与否（selected 为 true 则选中）
		 */
    toggleRowSelection (row, selected) {
      // if (!this.theadChildren) return
      row = [].concat(row)

      this.trChildren.forEach((item, index) => {
        // if (item.keyValue) {

        const select = row.findIndex(v => {
          //
          if (typeof v === 'number') {
            return v === index - 1
          } else {
            return v[this.rowKey] === item.keyValue
          }
        })
        const ischeck = item.checked
        if (select !== -1) {
          if (typeof selected === 'boolean') {
            item.checked = selected
          } else {
            item.checked = !item.checked
          }
          if (ischeck !== item.checked) {
            this.check(item.rowData || item, item.checked, item.rowData ? item.keyValue : null, true)
          }
        }
        // }
      })
      this.$emit('selection-change', {
        detail: {
          value: this.backData,
          index: this.backIndexData
        }
      })
    },

    /**
		 * 用于多选表格，清空用户的选择
		 */
    clearSelection () {
      let theadChildren = this.theadChildren
      if (!this.theadChildren) {
        theadChildren = this.trChildren[0]
      }
      // if (!this.theadChildren) return
      theadChildren.checked = false
      theadChildren.indeterminate = false
      this.trChildren.forEach(item => {
        // if (item.keyValue) {
        item.checked = false
        // }
      })
      this.backData = []
      this.backIndexData = []
      this.$emit('selection-change', {
        detail: {
          value: [],
          index: []
        }
      })
    },
    /**
		 * 用于多选表格，切换所有行的选中状态
		 */
    toggleAllSelection () {
      const list = []
      let startIndex = 1
      let theadChildren = this.theadChildren
      if (!this.theadChildren) {
        theadChildren = this.trChildren[0]
      } else {
        startIndex = theadChildren.rowspan - 1
      }
      this.trChildren.forEach((item, index) => {
        if (!item.disabled) {
          if (index > (startIndex - 1)) {
            list.push(index - startIndex)
          }
        }
      })
      this.toggleRowSelection(list)
    },

    /**
		 * 选中\取消选中
		 * @param {Object} child
		 * @param {Object} check
		 * @param {Object} rowValue
		 */
    check (child, check, keyValue, emit) {
      let theadChildren = this.theadChildren
      if (!this.theadChildren) {
        theadChildren = this.trChildren[0]
      }

      let childDomIndex = this.trChildren.findIndex((item, index) => child === item)
      if (childDomIndex < 0) {
        childDomIndex = this.data.findIndex(v => v[this.rowKey] === keyValue) + 1
      }
      const dataLen = this.trChildren.filter(v => !v.disabled && v.keyValue).length
      if (childDomIndex === 0) {
        check ? this.selectionAll() : this.clearSelection()
        return
      }

      if (check) {
        if (keyValue) {
          this.backData.push(child)
        }
        this.backIndexData.push(childDomIndex - 1)
      } else {
        const index = this.backData.findIndex(v => v[this.rowKey] === keyValue)
        const idx = this.backIndexData.findIndex(item => item === childDomIndex - 1)
        if (keyValue) {
          this.backData.splice(index, 1)
        }
        this.backIndexData.splice(idx, 1)
      }

      const domCheckAll = this.trChildren.find((item, index) => index > 0 && !item.checked && !item.disabled)
      if (!domCheckAll) {
        theadChildren.indeterminate = false
        theadChildren.checked = true
      } else {
        theadChildren.indeterminate = true
        theadChildren.checked = false
      }

      if (this.backIndexData.length === 0) {
        theadChildren.indeterminate = false
      }

      if (!emit) {
        this.$emit('selection-change', {
          detail: {
            value: this.backData,
            index: this.backIndexData
          }
        })
      }
    }
  }
}
</script>

<style lang="scss">
$border-color: #ebeef5;

.uni-table-scroll {
	width: 100%;
	/* #ifndef APP-NVUE */
	overflow-x: auto;
	/* #endif */
}

.uni-table {
	position: relative;
	width: 100%;
	border-radius: 5px;
	// box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);
	background-color: #fff;
	/* #ifndef APP-NVUE */
	box-sizing: border-box;
	display: table;
	overflow-x: auto;
	::v-deep .uni-table-tr:nth-child(n + 2) {
		&:hover {
			background-color: #f5f7fa;
		}
	}
	::v-deep .uni-table-thead {
		.uni-table-tr {
			// background-color: #f5f7fa;
			&:hover {
				background-color:#fafafa;
			}
		}
	}
	/* #endif */
}

.table--border {
	border: 1px $border-color solid;
	border-right: none;
}

.border-none {
	/* #ifndef APP-NVUE */
	border-bottom: none;
	/* #endif */
}

.table--stripe {
	/* #ifndef APP-NVUE */
	::v-deep .uni-table-tr:nth-child(2n + 3) {
		background-color: #fafafa;
	}
	/* #endif */
}

/* 表格加载、无数据样式 */
.uni-table-loading {
	position: relative;
	/* #ifndef APP-NVUE */
	display: table-row;
	/* #endif */
	height: 50px;
	line-height: 50px;
	overflow: hidden;
	box-sizing: border-box;
}
.empty-border {
	border-right: 1px $border-color solid;
}
.uni-table-text {
	position: absolute;
	right: 0;
	left: 0;
	text-align: center;
	font-size: 14px;
	color: #999;
}

.uni-table-mask {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	background-color: rgba(255, 255, 255, 0.8);
	z-index: 99;
	/* #ifndef APP-NVUE */
	display: flex;
	margin: auto;
	transition: all 0.5s;
	/* #endif */
	justify-content: center;
	align-items: center;
}

.uni-table--loader {
	width: 30px;
	height: 30px;
	border: 2px solid #aaa;
	// border-bottom-color: transparent;
	border-radius: 50%;
	/* #ifndef APP-NVUE */
	animation: 2s uni-table--loader linear infinite;
	/* #endif */
	position: relative;
}

@keyframes uni-table--loader {
	0% {
		transform: rotate(360deg);
	}

	10% {
		border-left-color: transparent;
	}

	20% {
		border-bottom-color: transparent;
	}

	30% {
		border-right-color: transparent;
	}

	40% {
		border-top-color: transparent;
	}

	50% {
		transform: rotate(0deg);
	}

	60% {
		border-top-color: transparent;
	}

	70% {
		border-left-color: transparent;
	}

	80% {
		border-bottom-color: transparent;
	}

	90% {
		border-right-color: transparent;
	}

	100% {
		transform: rotate(-360deg);
	}
}
</style>
